/*
Copyright (c) 2006 Stanisław Pitucha

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

using System;
using Gtk;
using System.Text.RegularExpressions;

namespace GtkRegexTest {
public class MainWindow: Gtk.Window
{
	protected Gtk.TextView textMatchTest;
	protected Gtk.TextView textRegex;
	protected GtkRegexTest.RegexTree regexTree;
	protected Gtk.CheckButton checkOptECMA;
	protected Gtk.CheckButton checkOptCompiled;
	protected Gtk.CheckButton checkOptIgnoreCase;
	protected Gtk.CheckButton checkOptMultiline;
	
	public MainWindow (): base ("") {
		Stetic.Gui.Build (this, typeof(MainWindow));

		TextTag tt = new TextTag("match");
		tt.Background = "grey";
		textMatchTest.Buffer.TagTable.Add(tt);

		tt = new TextTag("group");
		tt.Background = "light blue";
		tt.Weight = Pango.Weight.Bold;
		textMatchTest.Buffer.TagTable.Add(tt);

		tt = new TextTag("capture");
		tt.Background = "green";
		tt.Weight = Pango.Weight.Bold;
		textMatchTest.Buffer.TagTable.Add(tt);

		// stupid stetic - remove when it's fixed
		regexTree.RegexTreeSelectionChange+=new RegexTree.RegexTreeSelectionChangeHandler(regexTreeSelectionChange);
	}
	
	protected void OnDeleteEvent (object sender, DeleteEventArgs a) {
		Application.Quit ();
		a.RetVal = true;
	}

	protected RegexOptions getOptions() {
		RegexOptions opts = RegexOptions.None;

		if(checkOptECMA.Active)
			opts|=RegexOptions.ECMAScript;
		if(checkOptMultiline.Active)
			opts|=RegexOptions.Multiline;
		if(checkOptCompiled.Active)
			opts|=RegexOptions.Compiled;
		if(checkOptIgnoreCase.Active)
			opts|=RegexOptions.IgnoreCase;
		
		return opts;
	}

	protected virtual void runClicked(object sender, System.EventArgs e) {
		string reString = textRegex.Buffer.Text;
		Regex re;
		try {
			re = new Regex(reString, getOptions());
		} catch(ArgumentException ex) {
			Utils.ShowInfo(
				this,
				String.Format("Error parsing \"{0}\"", ex.ParamName));
			return;
		}
		MatchCollection mc = re.Matches(textMatchTest.Buffer.Text);

		regexTree.Clear();
		regexTree.Add(mc);
	}


	protected virtual void regexTreeSelectionChange(object tv, GtkRegexTest.RegexTreeSelectionArgs e) {
		TextBuffer buf = textMatchTest.Buffer;
		buf.RemoveAllTags(buf.StartIter, buf.EndIter);
		buf.ApplyTag(
			"match",
			buf.GetIterAtOffset(e.Match[0]),
			buf.GetIterAtOffset(e.Match[0]+e.Match[1]) );
		if(e.Group!=null)
			buf.ApplyTag(
				"group",
				buf.GetIterAtOffset(e.Group[0]),
				buf.GetIterAtOffset(e.Group[0]+e.Group[1]) );
		if(e.Capture!=null)
			buf.ApplyTag(
				"capture",
				buf.GetIterAtOffset(e.Capture[0]),
				buf.GetIterAtOffset(e.Capture[0]+e.Capture[1]) );
		textMatchTest.ScrollToIter(buf.GetIterAtOffset(e.Match[0]+e.Match[1]/2), 0, true, 0.5, 0.5);
	}

	protected virtual void clickedSpeedTest(object sender, System.EventArgs e) {
		string reString = textRegex.Buffer.Text;
		string matchString = textMatchTest.Buffer.Text;

		Regex re;
		try {
			re = new Regex(reString, getOptions());
			re = null;
		} catch(ArgumentException ex) {
			Utils.ShowInfo(
				this,
				String.Format("Error parsing \"{0}\"", ex.ParamName));
			return;
		}
		
		DateTime start;
		TimeSpan runTime;
		
		start = DateTime.Now;
		for(int i=0;i<100;i++) {
			re = new Regex(reString, getOptions() & ~RegexOptions.Compiled);
		}
		runTime = DateTime.Now-start;
		double notCompiled = runTime.TotalMilliseconds/100;

		start = DateTime.Now;
		for(int i=0;i<100;i++) {
			re.Matches(matchString);
		}
		runTime = DateTime.Now-start;
		double notCompiledMatch = runTime.TotalMilliseconds/100;
		
		start = DateTime.Now;
		for(int i=0;i<100;i++) {
			re = new Regex(reString, getOptions() | RegexOptions.Compiled);
		}
		runTime = DateTime.Now-start;
		double compiled = runTime.TotalMilliseconds/100;
		
		start = DateTime.Now;
		for(int i=0;i<100;i++) {
			re.Matches(matchString);
		}
		runTime = DateTime.Now-start;
		double compiledMatch = runTime.TotalMilliseconds/100;
		
		Utils.ShowInfo(
			this,
			String.Format("Not compiled: {0}ms\nMatch: {1}ms\n\nCompiled: {2}ms\nMatch: {3}ms",
				notCompiled, notCompiledMatch, compiled, compiledMatch));
	}

	protected virtual void butEscapeClicked(object sender, System.EventArgs e) {
		TextIter begin, end;
		TextBuffer buf = textRegex.Buffer;
		bool selected = buf.GetSelectionBounds(out begin, out end);
		
		string toChange;
		if(selected) {
			toChange = buf.GetText(begin, end, true);
		} else {
			toChange = buf.Text;
		}
		
		Regex r = new Regex(@"([\\\(\)\[\^\$\.\?\*\+\|])");
		toChange = r.Replace(toChange, @"\\$1");
		
		if(selected) {
			int beginOff=begin.Offset;
			buf.DeleteSelection(false, false);
			
			end = buf.GetIterAtOffset(beginOff);
			buf.Insert(ref end, toChange);

			begin = buf.GetIterAtOffset(beginOff);
			buf.SelectRange(begin, end);
		} else {
			buf.Clear();
			begin = buf.StartIter;
			buf.Insert(ref begin, toChange);
		}
	}
}
}